package name.cyrax.red.jpv.impl.funcs;

import name.cyrax.red.jpv.api.adapters.DoubleAdapter;
import name.cyrax.red.jpv.api.adapters.IntegerAdapter;
import name.cyrax.red.jpv.api.adapters.LongAdapter;
import name.cyrax.red.jpv.api.funcs.Functor;
import name.cyrax.red.jpv.api.funcs.FunctorInstance;
import name.cyrax.red.jpv.api.funcs.info.FunctorMethod;
import name.cyrax.red.jpv.api.funcs.info.ValueType;
import name.cyrax.red.jpv.impl.funcs.core.AbstractFunctorInstance;

public enum DefaultFunctorInstances {
	ARRAY(
			FunctorMethod.newArrayGet(ValueType.INTEGER),
			FunctorMethod.newArrayGet(ValueType.LONG),
			FunctorMethod.newArrayGet(ValueType.DOUBLE)), 
	ADAPTER(
			FunctorMethod.newIndexGet(IntegerAdapter.class, "getInteger", ValueType.INTEGER),
			FunctorMethod.newIndexGet(LongAdapter.class, "getLong", ValueType.LONG),
			FunctorMethod.newIndexGet(DoubleAdapter.class, "getDouble", ValueType.DOUBLE)),
	CONST(
			FunctorMethod.newMethod(Integer.class, "intValue", ValueType.INTEGER),
			FunctorMethod.newMethod(Long.class, "longValue", ValueType.LONG),
			FunctorMethod.newMethod(Double.class, "doubleValue", ValueType.DOUBLE));

	public static final DefaultFunctorInstances VECTOR = ADAPTER;
	
	private FunctorMethod[] methods;
	
	private DefaultFunctorInstances(FunctorMethod fiInteger, FunctorMethod fiLong, FunctorMethod fiDouble) {
		methods = new FunctorMethod[ValueType.values().length];
		methods[ValueType.INTEGER.ordinal()] = fiInteger;
		methods[ValueType.LONG.ordinal()] = fiLong;
		methods[ValueType.DOUBLE.ordinal()] = fiDouble;
	}
	
	public final FunctorMethod getMethod(ValueType vt) {
		return methods[vt.ordinal()];
	}

	public final FunctorInstance getFunctorInstance(Functor functor, Object targetObject, ValueType vt) {
		return new AbstractFunctorInstance(functor, getMethod(vt), targetObject);
	}
	
	public static final Functor FUNCTOR_STUB_ADAPTER = new Functor() {
		
		@Override public String getName()
		{
			return "adapter";
		}
	};

	public static final Functor FUNCTOR_STUB_VECTOR = new Functor() {
		
		@Override public String getName()
		{
			return "vector";
		}
	};
}